【入門】Slack のコマンドを作ってみよう!(非同期実行版)
新年明けましておめでとうございます、本年も宜しくお願い致します! 前回の記事にて、Serverless Framework を利用した、同期実行版の Slack コマンドを作成しました。 Slack のスラッシュコマンドの仕様上、3秒 以内に処理を完了し Slack コマンドへレスポンスを返却する必要があるため、今回は非同期に処理を実行する Slack コマンドを作成してみたいと思います。 前回の記事(同期実行版)については、こちらからご参照ください。
Slack コマンド作ってみた
前回同様に GitHub にソースを Push しております。下記の手順にて async ブランチを clone してご利用ください。 同期実行版では、handler.py と serverless.yml しかありませんでしたが、今回 slack.py という Slack コマンド実行者へレスポンスを返却するための Lambda 関数が定義されたファイルを用意しています。
$ git clone -b async https://github.com/yuji-shimoda/hello-slack-command.git Cloning into 'hello-slack-command'... remote: Enumerating objects: 10, done. remote: Counting objects: 100% (10/10), done. remote: Compressing objects: 100% (9/9), done. remote: Total 10 (delta 2), reused 9 (delta 1), pack-reused 0 Unpacking objects: 100% (10/10), done. $ cd hello-slack-command/ $ git branch * async $ ls -l total 24 -rw-r--r-- 1 shimoda.yuji staff 2165 12 26 11:37 handler.py -rw-r--r-- 1 shimoda.yuji staff 1809 12 26 11:37 serverless.yml -rw-r--r-- 1 shimoda.yuji staff 633 12 26 11:37 slack.py
インターネットで公開されている記事を検索すると、Slack コマンドを非同期に処理する実装は SQS/SNS を利用するパターンが散見されますが、今回は AWS Step Functions を利用するパターンで実装してみました。
まずは、下記のリンクから Slack アプリを作成します。
表示されたウィンドウ内の App Name にアプリケーション名を、Development Slack Workspace に、このアプリケーションを利用する Slack のワークスペースを選択します。
定番ネタではありますが、Hello World アプリを作成します。Create App ボタンをクリックしましょう。
アプリケーションが作成されたら、Basic Information 画面が表示されます。まずはじめに必要な情報として、App Credentials の Signing Secret を取得します。少し下にスクロールしてください。
Signing Secret の横に設置された Show ボタンをクリックして、シークレット情報をコピーしておいてください。取得したシークレットは、Lambda から利用するために AWS Secrets Manager に保存します。利用している PC のターミナルを開いて、AWS CLI でシークレットを作成します。(acbde... となってる部分を、取得したシークレット情報に置き換えてください)
$ cat <<EOF > secret.json { "key": "abcdefghijklmnopqrstu123456789" } EOF $ aws secretsmanager create-secret \ --region ap-northeast-1 \ --name slack/secret \ --secret-string file://secret.json { "ARN": "arn:aws:secretsmanager:ap-northeast-1:012345678901:secret:slack/secret-QF4hfm", "Name": "slack/secret", "VersionId": "8612e5ec-c620-4d4c-9249-xxxxxxxxxxxx" } $ rm -f secret.json
次に Slack コマンドからのリクエストを受け取る API Gateway と Lambda および非同期に処理を実行するための Step Functions(ステートマシン)と Slack コマンドへレスポンスを返却するための Lambda を作成していきます。前回同様デプロイ作業は、sls deploy コマンドを実行するのみです。事前の準備として serverless-python-requirements や serverless-step-functions プラグイン、boto3 等の必要なライブラリをインストールしてから実行しましょう。
$ npm install -g serverless $ brew install pipenv $ sls plugin install -n serverless-python-requirements $ sls plugin install -n serverless-step-functions $ pipenv install boto3 requests $ sls deploy : Service Information service: async-hello stage: dev region: ap-northeast-1 stack: async-hello-dev resources: 15 api keys: None endpoints: POST - https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/ functions: hello: async-hello-dev-hello slack: async-hello-dev-slack
Serverless Framework により、API Gateway と Lambda 2つおよび StepFunctions のステートマシンが作成されました。POST - の後にある URL(https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/)が API Gateway のエンドポイントになります。Slack アプリ側で設定を行うためメモしておきましょう。
再度、Slack アプリ側の設定ページに戻り Slack コマンドを作成していきます。
Slash Commands をクリックします。
Create New Command ボタンをクリックします。
必須項目を埋めていきましょう。
項目 | 入力値 |
---|---|
Command | コマンド名 |
Request URL | API Gateway のエンドポイント |
Short Description | コマンドの簡単な説明 |
パラメータ入力後は、実際の利用イメージとしてプレビュー画面が更新表示されます。
Save ボタンをクリックしたら Slack コマンドの準備は完了です。 最後に Slack アプリをワークスペース内で有効化することで、コマンドが使用可能になります。
左袖メニューの「Install App」から、「Install App to Workspace」ボタンをクリックして、権限のリクエストを許可してあげてください。
Slack のメッセージ作成ボックスから /hello と入力してみましょう。
Slack コマンドにテキストを入力してみます。
送信ボタンを押すと
"Hello" + Slack コマンドの引数として「入力した文字列」の応答が返ってきました。
非同期実行版 Slack コマンドの概要
非同期実行版では、下記の流れで処理が実行されます。
- Slack コマンドのリクエストを API Gateway が受け取る
- API Gateway から Lambda が呼び出され、Slack コマンドのリクエストに含まれる response_url および入力されたテキストを取得する
- 入力されたテキストに "Hello " を付与し、response_url と共に、Step Functions の入力データを生成する
- Step Functions のステートマシンを起動する
- Slack コマンドのリクエストには、ステータスコード 200 と共に「しばらくお待ち下さい」というテキストを返却する
- ステートマシンから、Slack コマンドへのレスポンス応答用 Lambda を呼び出す
- ステートマシンの入力データを取得し、Slack コマンドへのレスポンスデータを生成する
- Slack コマンド(response_url)へ応答を返す
- Slack コマンドに、"Hello" + Slack コマンドの引数として「入力した文字列」が表示される
今回作成された ResponseHello ステートマシンは、下記のようにシンプルなワークフローとなります。
このソースをベースに、Slack へレスポンス応答を返す slack.py 側をカスタマイズすれば色々と遊べるはずです。 なお、その他の詳細等についてはソースコードをご参照ください。
さいごに
AWS Step Functions を利用して、Slack コマンドからのリクエストを非同期に処理することにより Slack 側の制限( 3秒 )に抵触することなく様々な処理を行うことが可能になります。皆さんのアイデア次第で可能性は無限に広がりますので、Slack コマンド作りに一度挑戦してみてはいかがでしょうか? ではでは